# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: jshin, leon

import coin.proto.coin_market_enums_pb2 as coin_enum
from coin.exchange.base.order_gateway_log_builder import (prepare_builder,
                                                          to_proto_order_side,
                                                          BaseOrderEventBuilder,
                                                          OrderEvent)
from coin.exchange.base.order_gateway_logger import OrderGatewayLogProvider
import coin.proto.coin_order_enums_pb2 as coin_order


class BitflyerOrderGatewayLogProvider(OrderGatewayLogProvider):
  exchange_type = coin_enum.Bitflyer

  def gen_order_event_and_log(self,
                              order,
                              timestamp,
                              order_event_type,
                              fill_price=None,
                              fill_qty=None,
                              fill_source=None,
                              external_order_id=None,
                              product_override=None,
                              order_side_override=None):
    product = product_override or order.product
    builder = prepare_builder(BaseOrderEventBuilder,
                              None,
                              timestamp,
                              self.get_next_order_event_id(),
                              self.exchange_type,
                              product.symbol)

    if order:
      external_order_id = order.internal.bitflyer_order_id
      builder.set_order(order, external_order_id)

    if external_order_id is not None:
      builder.oe.external_order_id = external_order_id

    if order_side_override is not None:
      builder.oe.order_side = to_proto_order_side(order_side_override)

    if order_event_type == OrderEvent.ORDER_ACCEPTED:
      order_state = coin_order.WORKING_ORDER
    elif order_event_type == OrderEvent.ORDER_FILLED:
      assert fill_price is not None
      assert fill_qty is not None
      order_state = coin_order.DEAD_ORDER
      builder.set_fill(fill_price, fill_qty, fill_source=fill_source)  # Unknown fill_type
    elif order_event_type in [
        OrderEvent.CANCEL_CONFIRMED, OrderEvent.ORDER_REJECTED, OrderEvent.ORDER_EXPIRED
    ]:
      order_state = coin_order.DEAD_ORDER
    else:
      raise NotImplementedError()

    order_event_source = OrderEvent.EXCHANGE
    builder.set_state(order_event_type=order_event_type,
                      order_state=order_state,
                      order_event_source=order_event_source)
    self.write_order_event(builder.oe)

  def gen_flush_expired_order_event_and_log(self, symbol, internal_order_id, timestamp):
    builder = prepare_builder(BaseOrderEventBuilder,
                              None,
                              timestamp,
                              self.get_next_order_event_id(),
                              self.exchange_type,
                              symbol)
    builder.oe.internal_order_id = internal_order_id

    builder.set_state(order_event_type=OrderEvent.ORDER_EXPIRED,
                      order_state=coin_order.DEAD_ORDER,
                      order_event_source=OrderEvent.USER)
    self.write_order_event(builder.oe)
